home *** CD-ROM | disk | FTP | other *** search
Text File | 1997-12-20 | 16.7 KB | 567 lines | [TEXT/ALFA] |
- ## -*-Tcl-*-
- # ###################################################################
- #
- # FILE: "clickUtils.tcl"
- # created: 11/2/96 {9:17:08 am}
- # last update: 20/12/97 {7:09:10 pm}
- # History
- #
- # Expanded version of old 'DblClickAux.tcl'
- #
- # Authors: Tom Pollard <pollard@chem.columbia.edu>
- # Tom Scavo <trscavo@syr.edu>
- # Vince Darley <darley@fas.harvard.edu>
- #
- # modified by rev reason
- # -------- --- --- -----------
- # 9/97 VMD 1.0 reorganised for new alpha distribution.
- # ###################################################################
- ##
-
- #############################################################################
- # Take any valid Macintosh filespec as input, and return the
- # corresponding absolute filespec. Filenames without an explicit
- # folder are resolved relative to the folder of the current document.
- #
- proc absolutePath {filename} {
- set name [file tail $filename]
- set subdir [file dirname $filename]
- if { [string length $subdir] > 0 && [string index $subdir 0] != ":" } {
- set dir ""
- } else {
- set dir [file dirname [lindex [winNames -f] 0]]
- }
- return "$dir$subdir:$name"
- }
-
- #############################################################################
- # Open the file specified by the full pathname "$filename"
- # If it's already open, just switch to it without any fuss.
- #
- proc openFileQuietly {filename} {
- if {[lsearch [winNames -f] $filename] >= 0} {
- bringToFront $filename
- } elseif {[file exists $filename]} {
- edit -w $filename
- } else {
- error "Couldn''t find \"$filename\""
- }
- }
-
- #############################################################################
- # Searches $filename for the given pattern $searchString. If the
- # search is successful, returns the matched string; otherwise returns
- # the empty string. If the flag 'indices' is true and the search is
- # successful, returns a list of two pos giving the indices of the
- # found string; otherwise returns the list '-1 -1'.
- #
- proc searchInFile {filename searchString {indices 0}} {
- # Get the text of the file to be searched:
- if {[lsearch [winNames -f] $filename] >= 0} {
- set fileText [getText -w $filename 0 [maxPos -w $filename]]
- } elseif {[file exists $filename]} {
- set fd [open $filename]
- set fileText [read $fd]
- close $fd
- } else {
- if { $indices } {
- return [list -1 -1]
- } else {
- return ""
- }
- }
- # Search the text for the search string:
- if { $indices } {
- if {[regexp -indices $searchString $fileText mtch]} {
- # Fixes an apparent bug in 'regexp':
- return [list [lindex $mtch 0] [expr [lindex $mtch 1] + 1]]
- } else {
- return [list -1 -1]
- }
- } else {
- if {[regexp $searchString $fileText mtch]} {
- return $mtch
- } else {
- return ""
- }
- }
- }
-
- #############################################################################
- # Read and return the complete contents of the specified file.
- #
- proc readFile {fileName} {
- if {[file exists $fileName] && [file readable $fileName]} {
- set fileid [open $fileName "r"]
- set contents [read $fileid]
- close $fileid
- return $contents
- } else {
- error "No readable file found"
- }
- }
-
- #############################################################################
- # Save $text in $filename. If $text is null, create an empty file.
- # Overwrite if $overwrite is true or the file does not exist;
- # otherwise, prompt the user.
- #
- proc writeFile {filename {text {}} {overwrite 0}} {
- if { $overwrite || ![file exists $filename] } {
- message "Saving $filename…"
- set fd [open $filename "w"]
- puts $fd $text
- close $fd
- } else {
- if [dialog::yesno "File $filename exists! Overwrite?"] {
- writeFile $filename $text 1
- } else {
- message "No file written"
- }
- }
- }
-
-
- #############################################################################
- # Highlight (select) a particular line in the designated file, opening the
- # file if necessary. Returns the full name of the buffer containing the
- # opened file. If provided, a message is displayed on the status line.
- #
- proc gotoFileLine {fname line {mesg {}}} {
- if {[lsearch [winNames -f] "*$fname"] >= 0} {
- bringToFront $fname
- } elseif {[lsearch [winNames] "*$fname"] >= 0} {
- bringToFront $fname
- } elseif {[file exists $fname]} {
- edit $fname
- catch {shrinkWindow 2}
- } else {
- alertnote "File \" $fname \" not found."
- return
- }
- set pos [rowColToPos $line 0]
- select [lineStart $pos] [nextLineStart $pos]
- if {[string length $mesg]} { message $mesg }
- return [win::Current]
- }
-
- ###########################################################################
- # Parse a string into "word"s, which include blocks of non-space text,
- # double- and single-quoted strings, and blocks of text enclosed in
- # balanced parentheses or curly brackets.
- #
- # If a word is delimited by a quote or paren character (\", \', \(, or \{),
- # then _that_ particular delimiter may be included within the word if it is
- # backslash-quoted, as above. No other characters are special or need quoting
- # with that word. The quoted delimiters are unquoted in the list of words
- # returned.
- #
- proc parseWords {entry} {
- set slash "\\"
- set qslash "\\\\"
-
- set words {}
- set entry [string trim $entry]
-
- while {[string length $entry]} {
- set delim [string range $entry 0 0]
- set entry [string range $entry 1 end]
-
- # regexp $endPat matches the end of the word
- # $openPat matches the open delimiter
- # $unescPat matches escaped instances of the open/close delimiters
- #
- # $type == "quote" means open/close delimiters are the same
- # == "paren" means there's a close delimiter and nesting is possible
- # == "unquoted" means the word is delimited by whitespace.
- #
- if {$delim == {"}} { set endPat {^([^"]*)"}
- set unescPat {\\(")}
- set type quote
-
- } elseif {$delim == {'}} { set endPat {^([^']*)'}
- set unescPat {\\(')}
- set type quote
-
- } elseif {$delim == "\{"} { set endPat "^(\[^\}\]*)\}"
- set openPat "\{"
- set unescPat "\\\\(\[\{\}\])"
- set type paren
-
- } elseif {$delim == "("} { set endPat {^([^)]*)\)}
- set openPat {(}
- set unescPat {\\([()])}
- set type paren
-
- } else { set type unquoted
- }
-
- if {$type == "quote"} {
- set ck $qslash
- set fld ""
- while {$ck == $qslash} {
- set ok [regexp -indices $endPat $entry mtch sub1]
- if {$ok} {
- append fld [string range $entry [lindex $mtch 0] [lindex $mtch 1]]
- set ck $slash[string range $entry [lindex $sub1 1] [lindex $sub1 1]]
- set pos [expr 1 + [lindex $mtch 1]]
- set entry [string range $entry $pos end]
- } else {
- error "Couldn't match $delim as field delimiter"
- }
- }
- set pos [expr [string length $fld] - 2]
- set fld [string range $fld 0 $pos]
- regsub -all $unescPat $fld {\1} fld
-
- } elseif {$type == "paren"} {
-
- set nopen 1
- set nclose 0
- set fld ""
- while {$nopen - $nclose != 0} {
- set ok [regexp -indices $endPat $entry mtch sub1]
- if {$ok} {
- append fld [string range $entry [lindex $mtch 0] [lindex $mtch 1]]
- set ck $slash[string range $entry [lindex $sub1 1] [lindex $sub1 1]]
- set entry [string range $entry [expr 1 + [lindex $mtch 1]] end]
- regsub -all $unescPat $fld {} fld1
- set nopen [llength [split $fld1 $openPat]]
- if {$ck != $qslash} { incr nclose }
- } else {
- error "Couldn't match $delim as field delimiter"
- }
- }
- set pos [expr [string length $fld] - 2]
- set fld [string range $fld 0 $pos]
- regsub -all $unescPat $fld {\1} fld
-
- } elseif {$type == "unquoted"} {
-
- set entry ${delim}${entry}
- set ok [regexp -indices {^([^ ]*)} $entry mtch sub1]
- if {$ok} {
- set fld [string range $entry [lindex $sub1 0] [lindex $sub1 1]]
- set pos [expr 1 + [lindex $mtch 1]]
- set entry [string range $entry $pos end]
- } else {
- set fld ""
- set entry ""
- }
- } else {
- error "parseWords: unrecognized case"
- }
-
- lappend words $fld
- set entry [string trimleft $entry]
- }
- return $words
- }
-
- ##
- # -------------------------------------------------------------------------
- #
- # "buildSubMenu" --
- #
- # Given a list of folders, 'buildSubMenu' returns a hierarchical menu based
- # on the files and subfolders in each of these folders. Pathnames are
- # optionally stored in a global array given by the argument 'filePaths'.
- # The path's index in this array is formed by concatenating the submenu
- # name and the filename, allowing the pathname to be retrieved by the
- # procedure 'proc' when the menu item is selected.
- #
- # The search may be restricted to files with specific extensions, or files
- # matching a certain pattern. A search depth may also be given, with three
- # levels of subfolders assumed by default.
- #
- # See MacPerl.tcl or latexMenu.tcl for examples.
- #
- # (originally written by Tom Pollard, with modifications by Vince Darley
- # and Tom Scavo)
- #
- # --Version--Author------------------Changes-------------------------------
- # 1.0 Tom Pollard original
- # 2.0 <vince@das.harvard.edu> multiple extensions, optional paths
- # 2.1 Tom Scavo multiple folders
- # 2.2 <vince@das.harvard.edu> pattern matching as well as exts
- # 2.3 <vince@das.harvard.edu> handles unique menu-names and does text only
- # -------------------------------------------------------------------------
- ##
- proc buildSubMenu {folders name proc {filePaths ""} {exts ""} {depth 3} {fset ""}} {
- global filesetmodeVars
- if { $filePaths != "" } {
- global $filePaths
- }
-
- incr depth -1
- set overallMenu {}
- foreach folder $folders {
- if {[file exists $folder]} {
- if {![file isdirectory $folder]} {
- set folder "[file dirname $folder]:"
- }
- if {[string length [file tail $folder]] > 0} {
- set folder "$folder:"
- }
- if {$name == 0} {
- set name [file tail [file dirname $folder]]
- }
- # if it's a fileset, we register _before_ recursing
- if { $fset != "" } {
- set mname [registerFilesetMenuName $fset $name $proc]
- } else {
- set mname $name
- }
- set menu {}
- if $filesetmodeVars(includeNonTextFiles) {
- set filenames [glob -nocomplain ${folder}*]
- } else {
- set filenames [lsort -ignore [concat [glob -nocomplain ${folder}*:] \
- [glob -nocomplain -t TEXT ${folder}*]]]
- }
- foreach m $filenames {
- if {[file isdirectory $m] && $depth > 0} {
- set subM [buildSubMenu [list ${m}] 0 $proc $filePaths $exts $depth $fset]
- if { $subM != "" } { lappend menu $subM }
- } elseif {[file isfile $m]} {
- set fname [file tail $m]
- if { $exts == "" || [lsearch ${exts} [file extension $fname] ] != -1 \
- || [string match $exts $fname] } {
- lappend menu $fname
- if { $filePaths != "" } {
- set ${filePaths}($name:$fname) $m
- }
- }
- }
- }
-
- if { $menu != "" } {
- set overallMenu [concat $overallMenu $menu]
- }
- } else {
- beep
- alertnote "buildSubMenu: Folder $folder does not exist!"
- }
- }
-
- if { $overallMenu != "" } {
- if { [string length $proc] > 1 } {
- set pproc "-p $proc"
- } else {
- set pproc ""
- }
- if { $fset != "" } {
- if { [string length $proc] > 1 } { set pproc "-p subMenuProc" }
- }
- return [concat {menu -m -n} [list $mname] $pproc [list $overallMenu]]
-
- } else {
- return ""
- }
- }
-
- # in case we've done something odd elsewhere
- ensureset filesetmodeVars(includeNonTextFiles) 0
-
- #############################################################################
- # Return a list of all subfolders found within $folder,
- # down to some maximum recursion depth. The top-level
- # folder is not included in the returned list.
- #
- proc listSubfolders {folder {depth 3}} {
- set folders {}
- if {$depth > 0} {
- incr depth -1
- if {[string length [file tail $folder]] > 0} {
- set folder "$folder:"
- }
- foreach m [glob -nocomplain $folder\*] {
- if {[file isdirectory $m]} {
- set folders [concat $folders [list $m]]
- set folders [concat $folders [listSubfolders ${m}: $depth]]
- }
- }
- }
- return $folders
- }
-
- #############################################################################
-
- proc commandClick {from to url} {
- select $from
- for {set i 0} {$i < 200} {incr i} {}
- select $from $to
- for {set i 0} {$i < 200} {incr i} {}
- select $from
- for {set i 0} {$i < 200} {incr i} {}
- select $from $to
- icURL $url
- }
-
- # Now doesn't add anything extra for windows which are not saved to disk.
- # To deal with shells and other similar windows. More general than only doing this for
- # shell mode.
- proc getIncludeFiles {} {
- global minItemsInTitlePopup
- if {([catch {mode::proc OptionTitlebar} lines] \
- || [llength $lines] < $minItemsInTitlePopup) \
- && [file exists [stripNameCount [win::Current]]]} {
- pushd [file dirname [win::Current]]
- if {[info exists lines] && $lines != ""} {
- eval lappend lines "-" [glob *]
- } else {
- set lines [glob *]
- }
- popd
- }
- return $lines
- }
-
- ##
- # -------------------------------------------------------------------------
- #
- # "editIncludeFile" --
- #
- # Called when you select an item from the option-click pop-up. Call a
- # mode-specific procedure if possible, else assume it's a file in the
- # same directory as the current window, and open it. If the mode specific
- # procedure ends in an error, we use the default version.
- # -------------------------------------------------------------------------
- ##
- proc editIncludeFile {item} {
- if [catch {mode::proc OptionTitlebarSelect $item}] {
- if {[file isdirectory "[file dirname [win::Current]]:$item"]} {
- file::showInFinder "[file dirname [win::Current]]:$item"
- } else {
- file::tryToOpen [list $item]
- }
- }
- }
-
-
- namespace eval file {}
-
- proc file::showInFinder {{f ""}} {
- if {$f == ""} {set f [win::Current]}
- openFolder [file dirname $f]
- switchTo Finder
- }
-
- proc file::tryToOpen {{fname ""}} {
- if {$fname == ""} {set fname [getSelect]}
- set f "[file dirname [win::Current]]:${fname}"
- if [file exists $f] {
- openFileQuietly $f
- } else {
- alertnote "Sorry, I couldn't find that file. You could install\
- Vince's Additions which includes better include-path handling."
- }
- }
-
-
- # Called from Alpha when titlebar "title" menu selected (command-mouse).
- proc getTitleBarPath {} {
- global fetched
-
- set f [win::Current]
- if {[info exists fetched($f)]} {
- set nm "[car $fetched($f)]/[cadr $fetched($f)]/[file tail $f]"
- regsub -all {//} $nm {/} nm
- regsub -all {/} $nm {:} nm
- return $nm
- } else {
- return $f
- }
- }
-
- proc titlebar {name} {
- global fetched
-
- if {[info exists fetched([win::Current])]} {
- set specs $fetched([win::Current])
- regexp {[^:]*:(.*)} $name dummy dir
- if {[regexp {:} $dir]} {
- regexp {(.*):([^:]*)} $dir dummy dir fname
- } else {
- set fname ""
- }
- regsub -all {:} $dir {/} dir
- ftpBrowse [car $specs] $dir [caddr $specs] [cadddr $specs] $fname
- } else {
- if [key::shiftPressed] {
- openFolder $name
- switchTo Finder
- } else {
- findFile $name
- }
- }
- }
-
- #===============================================================================
-
- proc cmdDoubleClick {{from -1} {to -1} {shift 0} {option 0} {control 0}} {
- global mode
-
- if {[expandURL] != ""} {
- sendUrl [getSelect]
- } else {
- if {$from < 0} {
- set from [getPos]
- set to [selEnd]
- if {$from == $to} {
- hiliteWord
- set from [getPos]
- set to [selEnd]
- }
- }
- if {[set proc [mode::getProc DblClick]] != ""} {
- if {[llength [info args $proc]] == 2} {
- $proc $from $to
- } else {
- $proc $from $to $shift $option $control
- }
- } else {
- message "No docs"
- }
- }
- }
-
- # (WTP 7/30/95) Slightly improved 'sendUrl'.
- # By accepting a text arg, this can now be used to make sendUrl
- # hypertext links (useful for "mailto" links in documentation, f'rinstance)
- #===============================================================================
- set htmlEventSuiteIDs(MOSS) {WWW!}
- set htmlEventSuiteIDs(MSIE) {WWW!}
-
- proc sendUrl {{text {}}} {
- if {$text == {}} { catch {set text [getSelect]} }
- if {$text == {}} { set text [prompt {URL?} {}] }
- if {[string length $text] == 0} { return }
-
- global htmlEventSuiteIDs browserSig browserSigs
-
- set name [file tail [app::launchAnyOfThese $browserSigs browserSig \
- "Please locate your web browser:"]]
-
- if {![info exists htmlEventSuiteIDs($browserSig)]} {
- alertnote "Can't send URLs to this HTML browser"
- return
- }
- set suite $htmlEventSuiteIDs($browserSig)
-
- AEBuild "'${browserSig}'" $suite {OURL} {----} "“$text”"
- switchTo $name
- }
-
-
- proc expandURL {} {
- set pos [getPos]
- set beg [lineStart $pos]
- if {[string length [set whe [search -s -n -f 1 -r 1 -i 1 -m 0 -l [nextLineStart $pos] {[a-zA-Z0-9]+://[a-zA-Z/._0-9~-]+} $beg]]]} {
- if {($pos >= [lindex $whe 0]) && ($pos < [lindex $whe 1])} {
- eval select $whe
- return $whe
- }
- }
- }
-